/**
 * Copyright (c) [2025] [何屹林]
 *
 * 保留所有权利。
 *
 * 文件名称：LR_1_TableShow.cpp
 * 模块功能说明：
 * 该模块实现逻辑处理类中关于LR1的分析表相关运算，相关内容展示接口
 *
 * 华南师范大学-计算机学院-网络工程-1班
 * 作者：何屹林-20222132023
 * 完成日期：2025年7月24日
 */
#include "logic.h"

void Logic::lr1_TableShow(const QString& title)
{
    Item first_item(start_sign,*grammars[start_sign].begin(),QSet<QString>({"$"}),0);       //初规则
    State first_state;                                                                      //初状态
    first_state.st.insert(first_item);

    for(auto n_final: nonFinalizers)                                                        //补充全部对应简化规则
    {
        for(auto list:grammars[n_final])
        {
            Gram g(n_final,list);
            Grams.push_back(g);
        }
    }
    first_state=State::closure(first_state,grammars,nonFinalizers,first_set);               //闭包运算

    LR1 lr1;                                                                                //lr1类

    lr1.state_hash[first_state] = lr1.size++;
    lr1.buildLR1(first_state, grammars, nonFinalizers, first_set, follow_set,Grams);


    //以上生成对应的LR1文法
    QStringList header,colHeader;
    int address_dollar;
    QSet<QString> finalString;

    for (int i = 0; i < lr1.size; i++)
        for (auto changeMethod: lr1.change_hash[i].keys())      //移进项集合
            if (!nonFinalizers.contains(changeMethod))
                finalString.insert(changeMethod);

    QVector<QVector<QString>> contentTable(lr1.state_hash.size()+1,QVector<QString>(finalString.size()+nonFinalizers.size()+1));

    QList<QString> finalStringList;
    for(auto f: finalString) finalStringList.append(f);

    QList<QString> nonFinalStringList;
    for(auto f:nonFinalizers) nonFinalStringList.append(f);

    std::sort(finalStringList.begin(), finalStringList.end());
    std::sort(nonFinalStringList.begin(), nonFinalStringList.end());//排序后的非终结符

    colHeader.append("状态");

    // 计算 "$" 在终结符列的位置
    finalStringList.append("$");
    address_dollar = finalStringList.indexOf("$");              //加上终结符作为总移进项

    // 表头结构：终结符（动作） + 非终结符（转移）
    header.append(finalStringList);  // 终结符部分（Action）
    header.append(nonFinalStringList);  // 非终结符部分（Goto）
    actionList=header;


    for(int i=0;i<lr1.state_hash.size();i++) colHeader.push_back(QString::number(i));


    for(int i=0;i<header.size();i++){
        contentTable[0][i]=header[i];
        header[i]=QString::number(i);
    }

    QVector<QVector<LR1TableItem>> tempTable(lr1.state_hash.size(),QVector<LR1TableItem>(header.size()));

    for (int i = 0; i < lr1.state_hash.size(); i++){
        // 处理终结符（移进/规约）

        for (int j = 0; j < finalStringList.size(); j++) {
            QString symbol = finalStringList[j];
            QString cell;
            LR1TableItem it;

            if (lr1.change_hash.value(i).contains(symbol)) {
                cell = "S" + QString::number(lr1.change_hash[i][symbol]);
                it.kind=1;
                it.idx=lr1.change_hash[i][symbol];
            } else if (lr1.reduce_hash.value(i).contains(symbol)) {
                cell = "R" + QString::number(lr1.reduce_hash[i][symbol]);//!!!!!
                it.kind=2;
                it.idx=lr1.reduce_hash[i][symbol];//!!!!!!!!!!!!!
                if(lr1.reduce_hash[i][symbol]==0&&j==address_dollar){
                    cell="ACCEPT";
                    it.kind=4;
                    it.idx=lr1.change_hash[i][symbol];
                }
            }
            contentTable[i+1][j]=cell;
            tempTable[i][j]=it;
        }
        //非终结符
        for (int j = 0; j < nonFinalStringList.size(); j++) {
            QString nonTerminal = nonFinalStringList[j];
            LR1TableItem it;

            int col = finalStringList.size() + j;
            if (lr1.change_hash.value(i).contains(nonTerminal)) {
                contentTable[i+1][col]=QString::number(lr1.change_hash[i][nonTerminal]);
                it.kind=3;
                it.idx=lr1.change_hash[i][nonFinalStringList[j]];
                tempTable[i][j+finalStringList.size()]=it;
            }
        }
    }

    LR1Table=tempTable;

    formShow(title,header,colHeader,contentTable);
    return;
}
